home *** CD-ROM | disk | FTP | other *** search
- //********************************************************************
- // INTSUM.CPP - Display/search program for Ralf Brown's
- // Interrupt List.
- //
- // Copyright (c) 1996 Daniel D. Miller
- //
- // Last Update: 09-08-95 08:42pm
- //
- // Compile with makefile
- //
- //********************************************************************
-
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <dos.h>
- #include <graph.h>
- #include "intsum.hpp"
- #include "err_exit.hpp"
- #include "keycodes.h"
- // #include <memcheck.h>
-
- //*****************************************************************
- main(int argc, char** argv)
- {
- int done, count ;
- unsigned j ;
- uchar char_attr ;
-
- // make sure at least DOS 3.0 is running
- if (_osmajor < 3)
- error_exit(OLD_DOS_VERSION, NULL) ;
-
- // get path for executable file
- _splitpath(argv[0], inidrive, inipath, NULL, NULL) ;
-
- // calculate video parameters
- char_attr = get_char_attr() ;
- get_vsize() ;
- window_rows = screen_rows - DATA_TOP ; // base-1
- select_video_seg(0) ; // auto-detect video segment
-
- // initialize the path for IntList files,
- // before reading INI file.
- strcpy(ildrive, inidrive) ;
- strcpy(ilpath , inipath) ;
-
- // search for/parse INI file
- read_ini_file() ;
-
- // allocate raw-data read buffer
- readptr = new char[(unsigned) BFR_SIZE] ;
- if (readptr == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
-
- // allocate ref-file buffers
- ref.bfr[0] = new sum_conv[isl_lines] ;
- if (ref.bfr[0] == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
- ref.bfr[1] = new sum_conv[isl_lines] ;
- if (ref.bfr[1] == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
-
- // allocate ref-search buffer
- search.bfr = new sum_conv[isl_lines] ;
- if (search.bfr == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
-
- // allocate list-file buffers
- list.bfr[0] = new lines[list_lines] ;
- if (list.bfr[0] == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
- list.bfr[1] = new lines[list_lines] ;
- if (list.bfr[1] == NULL)
- error_exit(OUT_OF_MEMORY, NULL) ;
-
- // search for interrup.idx
- // Build it if not present
- //
- // NOTE: if files are opened in TEXT mode,
- // EOLs get translated from CRLF in file to \n in buffer,
- // and "bytes read" is not what was asked for.
- // This program uses BINARY to solve some of these problems.
- _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
- index = fopen(tempstr, "rb") ;
- if (index == NULL)
- {
- build_index() ;
- _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
- index = fopen(tempstr, "rb") ;
- if (index == NULL)
- error_exit(NO_READ_FILE, "interrup.idx") ;
- }
- // leave ref file open
-
- // initialize variables and read first ref buffer
- ref.cur_bfr = 0 ;
- ref.offset = 0 ;
- fpos_t pos = 0 ;
- fill_ref_buffers(pos) ;
-
- //****************************************
- // hold off building display until
- // setup operations are successful.
- //****************************************
-
- // hide the cursor
- hide_cursor() ;
-
- // display our logo
- clear_display(MAIN_TEXT) ;
- display_logo() ;
-
- // display the first window
- display_ref_file() ;
-
- // main keyboard handler
- char srchstr[81] ;
- srchstr[0] = 0 ; // reset initial search string
- unsigned rtemp ;
- done = 0 ;
- while (!done)
- {
- mark_cursor_line(ivideo.currow, SELECTED) ;
- unsigned indata = get_key() ;
- mark_cursor_line(ivideo.currow, MAIN_TEXT) ;
- switch (indata)
- {
- case Key_ENTER: // seek info on current entry
- rtemp = ivideo.currow ;
- process_list_file(0, NULL) ;
- ivideo.currow = rtemp ;
- display_ref_file() ;
- break;
-
- case Key_UP:
- scroll_page_down() ;
- break;
-
- case Key_HOME:
- // position cursor at beginning of file
- pos = 0 ;
- fill_ref_buffers(pos) ;
- ref.offset = 0 ;
- ref.cur_bfr = 0 ;
- ivideo.currow = DATA_TOP ;
- display_ref_file() ;
- break;
-
- case Key_END:
- // seek end of file
- fseek(index, 0L, SEEK_END) ;
- fgetpos(index, &pos) ;
- pos -= REV_SIZE ;
-
- // adjust input-file position
- fsetpos(index, &pos) ;
- ref.hdptr[0] = pos ;
-
- // now read one line and re-position file pointer to full line
- count = seek_next_line(index) ;
- if (count < 0)
- error_exit(BAD_SEARCH, NULL) ;
- pos += count ;
- fill_ref_buffers(pos) ;
-
- // now, figure out which line is top of (end of screen)
- if (ref.lines[1] < window_rows)
- {
- ref.cur_bfr = 0 ;
- ref.offset = ref.lines[0] + ref.lines[1] - window_rows ;
- }
- else
- {
- ref.cur_bfr = 1 ;
- ref.offset = ref.lines[1] - window_rows ;
- }
-
- ivideo.currow = DATA_TOP ;
- display_ref_file() ;
- break;
-
- case Key_PGUP:
- rtemp = ivideo.currow ;
- ivideo.currow = DATA_TOP ;
- for (j=0; j<window_rows; j++)
- scroll_page_down() ;
- ivideo.currow = rtemp ;
- break;
-
- case Key_DOWN:
- scroll_page_up() ;
- break;
-
- case Key_PGDN:
- rtemp = ivideo.currow ;
- ivideo.currow = screen_rows - 1 ;
- for (j=0; j<window_rows; j++)
- scroll_page_up() ;
- ivideo.currow = rtemp ;
- break;
-
- case Key_F1:
- case Key_h:
- case Key_H: // display help screen
- display_help() ;
- display_logo() ;
- display_ref_file() ;
- break;
-
- case Key_F2:
- case Key_s:
- case Key_S: // search for string
- if (message_read("Enter string to search for: ", srchstr) == 0)
- {
- if (search_ref_buffers(srchstr) != 0)
- search_ref_file(srchstr) ;
- }
- break;
-
- case Key_F3:
- case Key_r:
- case Key_R: // repeat last string search
- if (strlen(srchstr) == 0)
- message_show("There is no current search string") ;
- else if (search_ref_buffers(srchstr) != 0)
- search_ref_file(srchstr) ;
- break;
-
- case Key_F4:
- case Key_t:
- case Key_T: // save current topic
- char sfile[81] ; // local storage for filename
- if (message_read("Enter filename to save to: ", sfile) == 0 &&
- strlen(sfile) > 0)
- {
- rtemp = ivideo.currow ;
- process_list_file(1, sfile) ;
- ivideo.currow = rtemp ;
- display_ref_file() ;
- }
- break;
-
- case Key_ESC:
- // delete buffers explicitly, so the allocations
- // aren't shown by memory checkers.
- delete readptr ;
- delete ref.bfr[0] ;
- delete ref.bfr[1] ;
- delete search.bfr ;
- delete list.bfr[0] ;
- delete list.bfr[1] ;
- done = 1 ;
- break;
-
- default:
- break;
- }
- }
-
- clear_display(char_attr) ;
- home_cursor() ;
- puts(THANKS_MESSAGE) ;
- puts(" Copyright (c) 1995 Dan Miller") ;
- puts(" derelict@netcom.com") ;
- return 0;
- }
-
- //*****************************************************************
- // read <UNDERSHOOT> bytes from (infile) into global (rdtemp),
- // then scan to beginning of next line and return number
- // of bytes to that next line.
- //*****************************************************************
- int seek_next_line(FILE* infile)
- {
- int count = 0 ;
- fread(rdtemp, 1, UNDERSHOOT, infile) ;
- int done = 0 ;
- while (!done)
- {
- if (rdtemp[count] == 0x0D || rdtemp[count] == 0x0A)
- {
- done = 1 ;
- while (rdtemp[count] == 0x0D || rdtemp[count] == 0x0A)
- {
- if (++count == UNDERSHOOT)
- return -1 ;
- }
- }
- else if (++count == UNDERSHOOT)
- return -1 ;
- }
- return count;
- }
-
- //*****************************************************************
- ulong make_laddr(char* instr)
- {
- ulong ts = ((ulong) FP_SEG(instr)) << 4 ; //lint !e740
- ulong to = (ulong) FP_OFF(instr) ; //lint !e740
- return ts + to ;
- }
-
- //*****************************************************************
- // NULL-terminates all lines in inbfr, by converting all
- // CR and LF into NULL. Also counts the lines and returns count.
- //*****************************************************************
- unsigned convert_lines(char* inbfr, unsigned rcount)
- {
- unsigned count = 0 ; // output line count
- unsigned bcount = 0 ; // input character count
- while (bcount < rcount)
- {
- if (*inbfr == 0x0D || *inbfr == 0x0A)
- {
- count++ ;
- while (*inbfr == 0x0D || *inbfr == 0x0A)
- {
- *inbfr++ = 0 ;
- bcount++ ;
- }
- }
- else
- {
- inbfr++ ;
- bcount++ ;
- }
- }
- return count ;
- }
-
- //*****************************************************************
- // parse lines from input file.
- // Back file up to
- //*****************************************************************
- unsigned fill_search_buffer(FILE* infile)
- {
- int done = 0 ;
- //lint -e740
- unsigned offseti = FP_OFF(readptr) ; // init value for byte tfr counter
- unsigned offsetf ;
- unsigned count = 0, j ;
-
- // fill the readbfr from ref file
- unsigned rlines = fill_read_buffer(infile) ;
- if (rlines == 0)
- return 0;
-
- // DEBUG:
- ulong iaddr = make_laddr(search.bfr[0].instr) ;
-
- // now, translate the read buffer into the ref-list buffer
- unsigned lcount = isl_lines ;
- char *sptr = readptr ;
- while (!done)
- {
- unsigned slen = strlen(sptr) ;
-
- // DEBUG:
- {
- ulong saddr = make_laddr(search.bfr[count].instr) ;
- if ((saddr+slen - iaddr) > (ulong) BFR_SIZE)
- {
- printf("\nSearch overrun:\n") ;
- printf("count = %d\n", count) ;
- printf("iaddr=%ld, saddr=%ld\n", iaddr, saddr) ;
- exit(1) ;
- }
- }
- strcpy(search.bfr[count].instr, sptr) ;
-
- // pad short lines with spaces
- if (slen < sizeof(sum_conv))
- {
- for (j=slen; j<last_ref_char; j++)
- search.bfr[count].instr[j] = ' ' ;
- // now, NULL-terminate the line
- search.bfr[count].instr[last_ref_char] = 0 ;
- }
-
- // point to next string in buffer
- sptr += slen ;
- while (*sptr == 0) sptr++ ; // skip NULLs at end of last line
-
- count++ ;
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- // If this terminates on lcount, rather than rlines,
- // the input buffer will have to be adjusted
- //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
- if (--lcount == 0 || count == rlines)
- {
- done = 1 ;
- // set tail-pointer variable in current ref struct
- offsetf = FP_OFF(sptr) ; //lint !e740
- search.tlptr = search.hdptr + (offsetf - offseti) ;
- fsetpos(infile, &search.tlptr) ; // adjust input-file position
- }
- }
-
- return count;
- }
-
- //*****************************************************************
- // Read a buffer-worth of raw data into readbfr,
- // do a partial read-and-fill to ensure that it contains
- // a full line at the end,
- // then replace all 0x0D and 0x0A with NULLs.
- // Return a count of lines.
- //
- // This routine reads from the current input file pointer
- //*****************************************************************
- unsigned fill_read_buffer(FILE* infile)
- {
- //***********************************************************
- // read data into read buffer and ensure even-line boundary.
- // This method assumes that the input file has already
- // been correctly positioned using fseek().
- //***********************************************************
- unsigned rbytes = fread(readptr, 1, ((unsigned) BFR_SIZE)-UNDERSHOOT, infile) ;
- if (rbytes == 0)
- return 0;
-
- //***********************************************************
- // FILL LAST LINE
- // if last line doesn't already end with a newline,
- // read more data to get there, and tack it on the end.
- //***********************************************************
- char* endptr = readptr + rbytes - 1 ;
- if (*endptr != 0x0D && *endptr != 0x0A)
- {
- unsigned slen = fread(rdtemp, 1, UNDERSHOOT, infile) ;
- if (slen == 0)
- error_exit(NO_READ_FILE, "reading infile") ;
-
- unsigned j=0;
- // search for newline (it MUST be there!!)
- while (rdtemp[j] != 0x0D && rdtemp[j] != 0x0A)
- {
- j++ ;
- if (j >= UNDERSHOOT)
- error_exit(BAD_FORMAT, rdtemp) ;
- }
- // then NULL-out and count the newlines
- while (rdtemp[j] == 0x0D || rdtemp[j] == 0x0A)
- {
- rdtemp[j] = 0 ;
- j++ ;
- if (j >= UNDERSHOOT)
- error_exit(BAD_FORMAT, rdtemp) ;
- }
- slen = j ;
-
- // copy the extra bytes into read buffer
- for (j=0; j<slen; j++)
- {
- *endptr++ = rdtemp[j] ;
- }
- rbytes += slen ;
- }
-
- // NULL-terminate and count the lines in read buffer.
- return convert_lines(readptr, rbytes) ;
- }
-
- //*****************************************************************
- void display_logo(void)
- {
- dprints(0, 0, LOGO, logo) ;
- dprints(0, 1, LOGO, dividers) ;
- dprints(0, 2, LOGO, header) ;
- dprints(0, 3, LOGO, dividerd) ;
- }
-
- //*****************************************************************
- // Build the indexed reference list
- //*****************************************************************
- void build_index(void)
- {
- union sum_conv outList ;
- char lname[_MAX_PATH] ;
- FILE* idxfile ;
- FILE* infile ;
- fpos_t fpos ;
- char instr[128], outstr[80] ;
- unsigned lflag ;
- char lext, extn[3] = ".x" ;
- unsigned long out_lines = 0L ;
-
- _makepath(tempstr, ildrive, ilpath, "interrup", "idx") ;
- idxfile = fopen(tempstr, "wb") ;
- if (idxfile == NULL)
- error_exit(NO_WRITE_FILE, "INTERRUP.IDX") ;
-
- puts(Version) ;
- puts("Building index file... this will take a couple of minutes") ;
-
- _makepath(lname, ildrive, ilpath, "interrup", "lst") ;
- infile = fopen(lname, "rb") ;
- if (infile == NULL) // then combined file does not exist; use parts
- {
- lflag = 0 ;
- lext = 'a' ;
- printf("reading INTERRUP.x sections: ") ;
- _makepath(lname, ildrive, ilpath, "interrup", "a") ;
- infile = fopen(lname, "rb") ;
- if (infile == NULL)
- {
- fclose(idxfile) ;
- unlink(tempstr) ;
- error_exit(NO_LIST_FILE, lname) ;
- }
- }
- else
- {
- lflag = 1 ;
- lext = ' ' ;
- printf("reading INTERRUP.LST: ") ;
- }
- fclose(infile) ;
-
- int done = 0 ;
- while (!done)
- {
- // open the next input file
- infile = fopen(lname, "rb") ;
- // if next file can't be opened, we're done!!
- if (infile == NULL)
- {
- fclose(idxfile) ;
- printf("\nRef file contains %lu lines\n", out_lines) ;
- return ;
- }
- putchar(lext) ;
-
- fpos = 0L ;
- // now that the next List file is open,
- // start searching for divider lines
- while ((fgets(instr, 128, infile)) != NULL)
- {
- if (strncmp(instr, "--------", 8) == 0 &&
- instr[9] == '-' &&
- instr[8] != '!'
- )
- {
- out_lines++ ;
-
- // reset the output data field
- memset(outList.idx.data, ' ', 80) ;
-
- outstr[ 0] = ' ' ;
- outstr[ 1] = instr[10] ; // INT number
- outstr[ 2] = instr[11] ;
- outstr[ 3] = ' ' ;
- outstr[ 4] = instr[12] ; // AH contents
- outstr[ 5] = instr[13] ;
- outstr[ 6] = ' ' ;
- outstr[ 7] = instr[14] ; // AL contents
- outstr[ 8] = instr[15] ;
- outstr[ 9] = ' ' ;
- outstr[10] = instr[8] ; // classification
- outstr[11] = '>' ;
-
- outList.idx.file = lext ;
- sprintf(outList.idx.foffset, "%08lX", fpos) ;
- outList.idx.null_term = ' ' ; // replace NULL with SPACE in file
-
- // move instr up to description line
- fgets(instr, 128, infile) ;
-
- // Trim line to 80 chars
- int inlen = strlen(instr) ;
- while (instr[inlen-1] == 0x0D || instr[inlen-1] == 0x0A)
- {
- instr[--inlen] = 0 ;
- }
-
- strncpy(&outstr[12], &instr[8], 80-13) ; // append to outstr
- outstr[80] = 0 ; // add safety NULL-terminator
- strcpy(outList.idx.data, outstr) ;
- fprintf(idxfile, "%s\r\n", outList.instr) ;
- } // if line matches search pattern, add to index file
-
- fgetpos(infile, &fpos) ; // update input-file pointer
- } // if input file not yet empty
- fclose(infile) ;
- if (lext == ' ')
- {
- done = 1 ;
- fclose(idxfile) ;
- }
- else
- {
- extn[1] = ++lext ;
- _makepath(lname, ildrive, ilpath, "interrup", extn) ;
- }
- } // while not done parsing files
- }
-
-